package rov.data;


import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;


// provides easy access to sensor data such as: temp, current, voltage, etc.
public class SensorData
{
    public static final int START_PORT = 32002;

    private Socket mSock;
    private DataOutputStream mOut;
    private BufferedReader mIn;
    private double mX, mY, mZ, mDeltaT;
    private boolean mRunning;
    private Thread mUpdater;
    private List<ChangeListener> mListeners;
private int mNumVals;
private double[] mValues;
private char[] buf = new char[128];
private long last;


    public SensorData(String serverName, int port) throws IOException
    {
        mSock = new Socket(serverName, port);
        mOut = new DataOutputStream(mSock.getOutputStream());
        mIn = new BufferedReader(new InputStreamReader(mSock.getInputStream()));

        mListeners = Collections.synchronizedList(
                         new ArrayList<ChangeListener>());

        mUpdater = new Thread()
        {
            public void run()
            {
                while (true)
                    updateLoop();
            }
        };

        mUpdater.start();

mValues = new double[6];
//mDeltaT = 0.01;
    }

    // Start listening for orientation data.
    public void start()
    {
        if (!mRunning)
            mRunning = true;
    }

    // Stop listening for orientation data.
    public void stop()
    {
        if (mRunning)
            mRunning = false;
    }

    // Returns true if listening for orientation data.
    public boolean isActive()
    {
        return mRunning;
    }

    // A listener's stateChanged method will be invoked when
    // orientation data is received.
    // Listeners' stateChanged methods should execute quickly.
    // Try not to do anything besides save the values from the getXYZ methods.
    public void addListener(ChangeListener l)
    {
        mListeners.add(l);
    }

    public int getNumVals()
    {
        return mNumVals;
    }

    // thread-safe
    public double getValue(int index)
    {
        return mValues[index];
    }

    public double getDeltaT()
    {
        return mDeltaT;
    }

    // Reads orientation data from the network.
    // Invokes listeners' stateChanged event handlers.
    private void updateLoop()
    {
        readData();

        if (mRunning)
        {
            ChangeEvent e = new ChangeEvent(this);

            for (ChangeListener cl : mListeners)
            {
                cl.stateChanged(e);
            }
        }
    }

    private void readData()
    {
        String input = null;

        try
        {
            input = mIn.readLine();

            if (input.charAt(0) == 's')
                input = input.substring(1);

            mNumVals = 0;
            String[] values = input.split(";");

            for (int i = 0; i < values.length && i < mValues.length; i++)
            {
                mValues[i] = Double.parseDouble(values[i]);
                mNumVals = i + 1;
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (NumberFormatException e)
        {
            System.err.println("invalid sensor data: " + input);
        }
    }
}
